home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / cgazv5n4.arc / FILES.C < prev    next >
C/C++ Source or Header  |  1991-09-23  |  8KB  |  315 lines

  1. /******* FILES.C ************************************************
  2.  * File: files.c
  3.  * Author: John Rex
  4.  * Date: October, 1989
  5.  * Modified Mar. 1991 to use \ as delimiter and return upper case
  6.  * Compilers: MSC 5.1
  7.  *            Turbo C 2.0
  8.  * Operating Systems: DOS and OS/2
  9.  * Memory Models: any
  10.  * Purpose: file name manipulation routines:
  11.  *     normal_name() - normalize a partial file name to one with
  12.  *                drive and correct path (all \.. stuff removed)
  13.  *     add_ext()     - add a file extension
  14.  *     del_ext()     - delete file extension
  15.  *
  16.  * Compile time switches: TEST brings in a test driver
  17.  *                        OS2  to get OS/2 compile (MSC only)
  18.  *
  19.  * Sample OS/2 compile lines:
  20.  *  OS/2 only version: cl /G2 /DOS2 /Lp /DTEST files.c
  21.  *  OS/2 or DOS (bound): 
  22.  *          cl /G2 /DOS2 /Lp /DTEST files.c /Fbbfiles.exe
  23.  *
  24.  * Source code may be freely used if source is acknowledged
  25.  * Object code may be freely used
  26.  ***************************************************************/
  27.  
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32.  
  33. #if !defined (OS2)              /* DOS only stuff */
  34. #include <dos.h>
  35.  
  36. /* define our own versions to avoid bugs with MSC's versions */
  37. #define FP_GETOFF(p)  ((unsigned) (p))
  38. #define FP_GETSEG(p)  ((unsigned) ((unsigned long)(p) >> 16) )
  39.  
  40. union  REGS  dataregs;
  41. struct SREGS segregs;
  42.  
  43. #define _rax        dataregs.x.ax
  44. #define _rdx        dataregs.x.dx
  45. #define _rsi        dataregs.x.si
  46. #define _rds        segregs.ds
  47. #define _carryf        dataregs.x.cflag
  48. #define _doint(x)   int86x(x,&dataregs,&dataregs,&segregs)
  49.  
  50. #define DOS_CALL        0x21
  51. #define GET_DEF_DRIVE    0x1900
  52. #define GET_DIR            0x4700
  53.  
  54. #else                           /* OS/2 */
  55. #define INCL_DOS
  56. #define INCL_NOPM               /* save time - no PM stuff */
  57. #include <os2.h>
  58. #endif
  59.  
  60. #pragma page()
  61. #pragma subtitle("normal_name()")
  62. int def_drive(void), get_directory(int, char *);
  63.  
  64. /* the character we use to delimit subdirs in final product */
  65. #define delim   '\\'
  66.  
  67. char *normal_name(char *file, char *buffer)
  68.     /* given a filename of the form
  69.  
  70.         [d:][path or partial path]filename
  71.  
  72.    normal_name() will return a pointer to a string containing 
  73.    the fully expanded path to the file.  The partial path may 
  74.    use / or \ and it may use the .. operator for backup in a 
  75.    directory tree.  NULL is returned if the path parse fails.
  76.    The var buffer is used as the work area - the returned 
  77.    pointer will be to buffer (if it's not a NULL).
  78.     */
  79. {
  80.     char path[100];
  81.     char *p, *s, save;
  82.     int drive;
  83.  
  84.     /* first convert all \ & / to one style */
  85.     for (p = file; *p != '\0'; p++)
  86.         if (*p == '/')
  87.             *p = '\\';
  88.  
  89.     /* are we given a drive? */
  90.     if ((p = strchr(file, ':')) != NULL) 
  91.     {
  92.         if (p - file != 1)
  93.             return(NULL);    /* error */
  94.  
  95.         drive = tolower(file[0]) - 'a';
  96.         file += 2;
  97.     }
  98.     else
  99.         drive = def_drive();
  100.  
  101.     if (get_directory(drive, path + 1) == 0)
  102.         return(NULL);
  103.     path[0] = '\\';      /* DOS doesn't supply the leading \ */
  104.  
  105.     /* now, march thru given file name and append to path */
  106.  
  107.     /* if filename starts with '\', then must go back to root */
  108.     if (*file == '\\') 
  109.     {
  110.         path[1] = '\0'; /* set path to just a root */
  111.         file++;
  112.     }
  113.  
  114.     /* path should always end in \ */
  115.     if (path[strlen(path) - 1] != '\\')
  116.         strcat(path, "\\");
  117.  
  118.     /* now, look at each subdir in filename */
  119.     while((p = strchr(file, '\\')) != NULL) 
  120.     {
  121.         save = *++p;
  122.         *p = '\0';
  123.         if (file[0] == '.') { /* look at dot operator */
  124.             if (strcmp(file ,"..\\") == 0)  
  125.             {                   /* back up one subdir */
  126.                 s = strrchr(path, '\\'); /* find start of 
  127.                                             previous subdir */
  128.                 if (s == path)
  129.                     s++;
  130.                 else 
  131.                 {
  132.                     *s = '\0';  /* remove trailing and
  133.                                    find preceding \ */
  134.                     s = strrchr(path, '\\') + 1; 
  135.                 }
  136.  
  137.                 *s = '\0';
  138.             }
  139.             else
  140.                 ; /* ignore other . commands */
  141.         }
  142.         else /* a subdir name */
  143.             strcat(path, file);
  144.  
  145.         *p = save;
  146.         file = p;
  147.     }
  148.  
  149.     /* and append the file name */
  150.     strcat(path, file);
  151.  
  152.     /* return the fruit of our labors */
  153.     p = buffer;
  154.     p[0] = (char) ('A' + drive);
  155.     p[1] = '\0';
  156.     strcat(p, ":");
  157.     strcat(p, path);
  158.     for (s = p; *s != '\0'; s++) /* convert delimiters 
  159.                                     to final form */
  160.         if (*s == '\\')
  161.             *s = delim;
  162.         else
  163.             *s = (char) toupper(*s);
  164.  
  165.     return(p);
  166. }
  167.  
  168. static struct d_list  /* a place to keep a list of */
  169. {                     /*   things we've looked up  */
  170.     int drive;
  171.     char *dir;
  172.     struct d_list *next;
  173. } *d_head = NULL;
  174.  
  175. int def_drive() /* return current default drive. */
  176. {               /* 0 = A, 1 = B, etc.            */
  177.  
  178. #if !defined (OS2)
  179.     _rax = GET_DEF_DRIVE;
  180.     _doint(DOS_CALL);
  181.     return(_rax & 0xFF);
  182.  
  183. #else
  184.     USHORT usDriveNumber;
  185.     ULONG ulLogicalDrives;
  186.     DosQCurDisk(&usDriveNumber, &ulLogicalDrives);
  187.     return(usDriveNumber - 1);
  188. #endif
  189. }
  190.  
  191. int get_directory(drive, buffer) /* get current dir for drive */
  192. int drive;      /* 0 = A, 1 = B, etc. */
  193. char *buffer;    /* put result here */
  194. {
  195.     struct d_list *d_ptr;
  196.  
  197. #if defined(OS2)
  198.     USHORT cbPath;
  199. #endif
  200.  
  201.     /* do we already know this one? */
  202.     for (d_ptr = d_head; d_ptr != NULL; d_ptr = d_ptr -> next)
  203.         if (d_ptr -> drive == drive) { /* found it */
  204.             strcpy(buffer, d_ptr -> dir);
  205.             return(1);
  206.         }
  207.  
  208.     /* haven't looked this one up - find out about it */
  209. #if !defined(OS2)
  210.     buffer[0] = '\0';    /* terminate the buffer */
  211.     _rax = GET_DIR;
  212.     _rdx = (unsigned) (drive + 1);
  213.     _rds = FP_GETSEG((void far *) buffer);
  214.     _rsi = FP_GETOFF((void far *) buffer);
  215.  
  216.     _doint(DOS_CALL);
  217.  
  218.     if (_carryf)
  219.         return(0);    /* something went wrong */
  220.  
  221. #else /* OS/2 */
  222.     if (DosQCurDir(drive+1, buffer, &cbPath))
  223.         return (0); /* something went wrong */
  224. #endif
  225.  
  226.     else {     /* success */
  227.         /* store a copy of what we found */
  228.         d_ptr = (struct d_list *) malloc(sizeof(struct d_list));
  229.         d_ptr -> next = d_head;
  230.         d_head = d_ptr;
  231.         d_ptr -> drive = drive;
  232.         d_ptr -> dir = malloc((unsigned) (strlen(buffer) + 1));
  233.         strcpy(d_ptr -> dir, buffer);
  234.  
  235.         /* and return */
  236.         return(1);
  237.     }
  238. }
  239.  
  240. /* routines to add or remove file extensions */
  241.  
  242. char *last_dot(char *file)  /* find the dot of the 
  243.                                file.ext portion of a filename */
  244. {
  245.     char *s;
  246.  
  247.     if      ((s = strrchr(file, '/' )) != NULL) ;
  248.     else if ((s = strrchr(file, '\\')) != NULL) ;
  249.     else s = file;
  250.  
  251.     return(strrchr(s, '.'));
  252. }
  253.  
  254. void delext(file)    /* remove the extension from a file name */
  255. char *file;
  256. {
  257.     char *s;
  258.  
  259.     s = last_dot(file);
  260.     if (s != NULL)
  261.         *s = '\0';
  262. }
  263.  
  264. void addext(file, ext)  /* add an ext if none already there */
  265. char *file;
  266. char *ext;
  267. {
  268.     char *s;
  269.  
  270.     s = last_dot(file);
  271.     if (s == NULL) 
  272.     {
  273.         strcat(file, ".");
  274.         strcat(file, ext);
  275.     }
  276. }
  277.  
  278. #pragma subtitle("test driver")
  279.  
  280. #ifdef TEST
  281. int cdecl main(argc, argv)
  282. int argc;
  283. char **argv;
  284. {
  285.     char *s, buf[100], work[100];
  286.  
  287.     if (argc < 2)
  288.         puts("Syntax is: files file_1 file_2 ...\n");
  289.     else 
  290.     {
  291.         argc--;
  292.         argv++;
  293.         while(argc--) 
  294.         {
  295.             strcpy(buf, *argv++);
  296.             puts(buf);
  297.             puts(" is altered to ");
  298.             delext(buf);
  299.             addext(buf, "zzz");
  300.             puts(buf);
  301.             puts("\n");
  302.  
  303.             s = normal_name(buf, work);
  304.             puts(buf);
  305.             puts(" becomes ");
  306.             if (s != NULL)
  307.                 puts(s);
  308.             else
  309.                 puts("path parse failed");
  310.             puts("\n");
  311.             puts("\n");
  312.         }
  313.     }
  314. }
  315. #endif